#ifndef THREADPOOL_H
#define THREADPOOL_H

#include<thread>
#include<condition_variable>
#include<mutex>
#include<vector>
#include<queue>
#include<future>
#include<atomic>
#include <iostream>

class Queue
{
public:
    struct Node{
        std::function<void()> task;
        struct Node* next;
        std::atomic<int> flag;

        Node(std::function<void()> x) : task(x), next(nullptr), flag(0) {}
    };
private:
    std::atomic<volatile Node*> head_;
    volatile Node* tail_;
public:
    Queue(){
        volatile Node* newHead = new Node(nullptr);
        head_.store(newHead);
        tail_ = head_;
    }
    ~Queue(){
        volatile Node* deletNode = head_.load();
        while(deletNode){
            Node* next = deletNode->next;
            delete deletNode;
            deletNode = next;
        }
    }

    void Push(std::function<void()> x){
        Node *newNode = new Node(x);
        if(newNode==nullptr){
            std::cout<<"内存占用太多，分配失败"<<std::endl;
            return;
        }
        volatile Node* p=tail_; volatile Node* oldp=tail_;
        do{
            while(p->next!=nullptr) p=p->next;
        }while(__sync_bool_compare_and_swap(&(p->next), nullptr, newNode)!=true);
        __sync_bool_compare_and_swap(&(tail_), oldp, newNode);
    }

    std::function<void()> Pop(){
        volatile Node* h = NULL;
        Node* h_next = NULL;
	    while (true) {
		    if (h == NULL) {
			    h = head_.load();
			    continue;
		    }
		    if (!head_.compare_exchange_weak(h, NULL))
			    continue;
		    h_next = h->next;
		    break;
	    }
	    volatile Node* expected = NULL;
	    volatile Node* desired = h;
        std::function<void()> res;
	    if (h_next != NULL) {
		    res = h_next->task;
		    delete h;
		    desired = h_next;
	    }
	    bool flag = head_.compare_exchange_weak(expected, desired);
	    //assert(flag);
	    return res;
    }
};

class ThreadPool{
private:
    //是否停止
    bool m_stop;

    //现场数组
    std::vector<std::thread>m_thread;
    
    //任务队列，用了function，所以后面可以用future来获取线程执行结果
    Queue tasks;
public:
    explicit ThreadPool(size_t threadNumber):m_stop(false){
        for(size_t i=0;i<threadNumber;++i)
        {
            m_thread.emplace_back(
                [this](){
                    for(;;)
                    {
                        std::function<void()> task=tasks.Pop();
                        if(m_stop==true && task == nullptr)   return;
                        if(task != nullptr) task();
                    }
                }
            );
        }
    }

    ThreadPool(const ThreadPool &) = delete;    //拷贝全delete
    ThreadPool(ThreadPool &&) = delete;

    ThreadPool & operator=(const ThreadPool &) = delete;
    ThreadPool & operator=(ThreadPool &&) = delete;

    ~ThreadPool(){
        m_stop=true;
        for(auto& threads:m_thread)
        {
            threads.join(); //等待线程执行完毕
        }
    }

    template<typename F,typename... Args>
    auto submit(F&& f,Args&&... args)->std::future<decltype(f(args...))>{
        auto taskPtr=
        std::make_shared<
            std::packaged_task<
                decltype(f(args...))()
            >
        >(
            std::bind(std::forward<F>(f),std::forward<Args>(args)...)
        );

        if(m_stop) throw std::runtime_error("submit on stopped ThreadPool");
        tasks.Push([taskPtr](){ (*taskPtr)(); });
        return taskPtr->get_future();

    }
};

#endif //THREADPOOL_H